package com.xyz.aspect;

import com.xyz.entity.dto.LogLoginDTO;
import com.xyz.entity.dto.LogOperationDTO;
import com.xyz.entity.request.BaseIdNumber;
import com.xyz.entity.request.LoginRequest;
import com.xyz.service.SystemService;
import com.xyz.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author 黄盛杰
 * @date 2022/4/1
 */
@Aspect
@Component
public class LogAspect {
    private final SystemService service;

    public LogAspect(SystemService service) {
        this.service = service;
    }

    @Pointcut("execution(* com.xyz.controller.LoginController.login(..))")
    void login(){}

    @Pointcut("@annotation(com.xyz.annotation.LogOperation)")
    void operation(){}

    @Around("login()")
    public Object logLoginAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        Object proceed = joinPoint.proceed();
        Object[] args = joinPoint.getArgs();
        for (Object item : args) {
            if (item instanceof LoginRequest) {
                LoginRequest item1 = (LoginRequest) item;
                this.service.logLogin(new LogLoginDTO(item1.getIdNumber()));
            } else {
                throw new RuntimeException("运行错误");
            }
        }
        return proceed;
    }

    @Around("operation()")
    public Object logOperationAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取request
        final ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(requestAttributes)) {
            throw new RuntimeException();
        }
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token) || BooleanUtils.isFalse(JwtUtils.verify(token))) {
            throw new IllegalAccessException();
        }
        Object[] args = joinPoint.getArgs();
        Claims claims = JwtUtils.parseToken(token);
        String idNumber = String.valueOf(claims.get("idNumber"));
        Integer role = (Integer) claims.get("role");
        for (Object arg : args) {
            if (arg instanceof BaseIdNumber) {
                if (BooleanUtils.isFalse(role == 1)) {
                    BaseIdNumber arg1 = (BaseIdNumber) arg;
                    arg1.setIdNumber(idNumber);
                    args[0] = arg1;
                }
            }
        }
        Object proceed = joinPoint.proceed(args);
        this.service.logOperation(new LogOperationDTO(joinPoint.getSignature().getName(), idNumber));
        return proceed;
    }

}
